package com.hex.ds.hdrs.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

@Slf4j
public class MapUtil {
	/**
	 * 打印 String：value对象
	 * 
	 * @param map
	 * */
	public static void print(Map map) {
		if (map != null) {

			for (Object obj : map.keySet()) {
				String key = (String) obj;
				System.out.println("key=" + key + " value=" + map.get(key));

			}
		}
	}

	/**
	 * 对象转换成Map
	 * 
	 * @param obj
	 * @return Map
	 * */
	public static Map convertObjToMap(Object obj) {
		Map<String, Object> reMap = new HashMap<String, Object>();
		if (obj == null) {
            return null;
        }
		Field[] fields = obj.getClass().getDeclaredFields();
		try {
			for (int i = 0; i < fields.length; i++) {
				try {
					Field f = obj.getClass().getDeclaredField(
							fields[i].getName());
					f.setAccessible(true);
					Object o = f.get(obj);
					reMap.put(fields[i].getName(), o);
				} catch (NoSuchFieldException e) {

				} catch (IllegalArgumentException e) {

				} catch (IllegalAccessException e) {

				}
			}
		} catch (SecurityException e) {

		}
		return reMap;
	}

	/**
	 * Map转对象
	 * 
	 * @param map
	 * @param clazz
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws IntrospectionException
	 * @throws InstantiationException
	 */
	public static Object parseMap2Obj(Map map, Class clazz)
			throws IllegalArgumentException, IllegalAccessException,
			InvocationTargetException, IntrospectionException,
			InstantiationException {
		// 创建JavaBean对象
		Object obj = clazz.newInstance();
		// 获取类属性
		BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
		// 给JavaBean对象的属性赋值
		PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
		for (int i = 0; i < descriptors.length; i++) {
			PropertyDescriptor descriptor = descriptors[i];
			String propertyName = descriptor.getName();
			if (map.containsKey(propertyName)) {
				Object value = map.get(propertyName);
				Object[] args = new Object[1];
				args[0] = value;
				descriptor.getWriteMethod().invoke(obj, args);
			}
		}
		return obj;
	}

	@SuppressWarnings("rawtypes")
	public static <T> T toBean(Class<T> clazz, Map map) {
		T obj = null;
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			obj = clazz.newInstance(); // 创建 JavaBean 对象
			// 给 JavaBean 对象的属性赋值
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (int i = 0; i < propertyDescriptors.length; i++) {
				PropertyDescriptor descriptor = propertyDescriptors[i];
				String propertyName = descriptor.getName();
				if (map.containsKey(propertyName)) {
					// 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
					Object value = map.get(propertyName);
					if ("".equals(value)) {
						value = null;
					}
					Object[] args = new Object[1];
					args[0] = value;
					try {
						descriptor.getWriteMethod().invoke(obj, args);
					} catch (InvocationTargetException e) {
						System.out.println("字段映射失败");
					}
				}
			}
		} catch (IllegalAccessException e) {
			System.out.println("实例化 JavaBean 失败");
		} catch (IntrospectionException e) {
			System.out.println("分析类属性失败");
		} catch (IllegalArgumentException e) {
			System.out.println(e.getMessage());
			System.out.println("映射错误");
		} catch (InstantiationException e) {
			System.out.println("实例化 JavaBean 失败");
		}
		return (T) obj;
	}


	/**
	 * 对象转Map
	 * 
	 * @param obj
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws IntrospectionException
	 */
	public static Map parseObj2Map(Object obj) throws IllegalArgumentException,
			IllegalAccessException, InvocationTargetException,
			IntrospectionException {
		Class clazz = obj.getClass();
		Map map = new HashMap();
		// 获取类属性
		BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
		// 给JavaBean对象的属性赋值
		PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
		for (int i = 0; i < descriptors.length; i++) {
			PropertyDescriptor descriptor = descriptors[i];
			String propertyName = descriptor.getName();
			if (!("class").equals(propertyName)) {
				Method method = descriptor.getReadMethod();
				Object result = method.invoke(obj, new Object[0]);
				if (result != null) {
					map.put(propertyName, result);
				}
			} else {
				map.put(propertyName, "");
			}
		}
		return map;
	}

	/**
	 * 对象转Map,包括父类属性
	 * @param entity
	 * @return
	 * @throws IllegalAccessException
	 */
	public static Map<String, ?> Entity2Map(Object entity)  {
		Map map = new HashMap();
		try{
			Class<?> clazz = entity.getClass();
			List<Field> fieldList = new ArrayList<>();
			while (clazz != null){
				fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
				clazz = clazz.getSuperclass();//找到所有父类的属性
			}
			for (Field field : fieldList) {
				field.setAccessible(true);
				Object value = field.get(entity);
				if(null != value) {
					map.put(field.getName(), value);
				}
			}
		}catch (IllegalAccessException e){

			log.error("类型转换错误,原因: {}",e.getMessage(), e);
		}
		return map;
	}

	/**
	 * Map转成实体对象
	 *
	 * @param map   实体对象包含属性
	 * @param clazz 实体对象类型
	 * @return
	 */
	public static Object map2Object(Map<Object, Object> map, Class<?> clazz) {
		if (map == null) {
			return null;
		}
		Object obj = null;
		try {
			obj = clazz.newInstance();
			Class clz = obj.getClass();
			List<Field> fields = new ArrayList<>();
			while (clz != null){
				fields.addAll(Arrays.asList(clz.getDeclaredFields()));
				clz = clz.getSuperclass();//找到所有父类的属性
			}
			for (Field field : fields) {
				int mod = field.getModifiers();
				if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
					continue;
				}
				field.setAccessible(true);
				field.set(obj, map.get(field.getName()));
			}
		} catch (Exception e) {

		}
		return obj;
	}
}
